use std::fs::File;
use std::io::{Error, ErrorKind, Read, Seek, SeekFrom};
use std::path::PathBuf;

pub struct SourceParser {
    // 文件名
    filename: String,
    file: Option<File>,
    offset: u64,
}

// 读取源文件的方式：
pub enum SourceFileReadMode {
    AsBinary,    // 原文件为二进制文件
    AsHexString, // 原文件为Hex String
}

impl SourceParser {
    pub fn new() -> SourceParser {
        SourceParser {
            filename: String::from(""),
            file: None,
            offset: 0,
        }
    }

    pub fn set_src_file(&mut self, filename: &PathBuf) -> bool {
        self.filename = filename.to_string_lossy().trim().to_string();
        let file = File::open(&self.filename);
        if let Ok(f) = file {
            self.file = Some(f);
            self.offset = 0;
            true
        } else {
            false
        }
    }

    pub fn get_next_paragraph(
        &mut self,
        size: u64,
        rd_mode: &SourceFileReadMode,
    ) -> Result<Vec<u8>, std::io::Error> {
        if let Some(ref mut ff) = self.file {
            ff.seek(SeekFrom::Start(self.offset))?;

            match rd_mode {
                SourceFileReadMode::AsBinary => {
                    // 按照 binary 读取
                    let mut buffer = vec![0; size as usize];
                    let bytes_read = ff.read(&mut buffer)?;
                    self.offset += bytes_read as u64;
                    buffer.truncate(bytes_read); // Truncate the buffer to the number of bytes actually read
                    return Ok(buffer);
                }
                SourceFileReadMode::AsHexString => {
                    // 按照HEX string 读取
                    let mut hex_str = String::with_capacity(size as usize); // Each byte is represented by 2 hex characters
                    let mut buffer = vec![0; size as usize * 2];
                    let bytes_read = ff.read(&mut buffer)?;
                    self.offset += bytes_read as u64;
                    buffer.truncate(bytes_read); // Truncate the buffer to the number of bytes actually read

                    // Convert the binary data to a string
                    hex_str.push_str(std::str::from_utf8(&buffer).unwrap().trim());

                    // Parse the hex string into u8 values
                    let hex_bytes = hex_str
                        .as_bytes()
                        .chunks(2)
                        .map(|chunk| {
                            u8::from_str_radix(std::str::from_utf8(chunk).unwrap(), 16).unwrap()
                        })
                        .collect();

                    return Ok(hex_bytes);
                }
            }
        }

        Err(std::io::Error::new(std::io::ErrorKind::Other, "文件未打开"))
    }

    pub fn read_from_sting(&self) -> Result<String, std::io::Error> {
        let mut file = File::open(&self.filename)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;

        Ok(contents)
    }

    pub fn read_from_binary(&self) -> Result<String, std::io::Error> {
        let mut file = File::open(&self.filename)?;
        let mut buffer = Vec::new();
        file.read_to_end(&mut buffer)?;

        // 将字节数组转换为16进制字符串
        let hex_string = buffer
            .iter()
            .map(|b| format!("{:02x}", b))
            .collect::<String>();

        Ok(hex_string)
    }
}
